package com.zmj.sy.mom.srv.aps.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.zmj.sy.mom.srv.aps.bean.bo.ApiResponse;
import com.zmj.sy.mom.srv.aps.bean.dto.feign.Ltk.LtkPushTokenDto;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.LogApi;
import com.zmj.sy.mom.srv.aps.mapper.LogApiMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Slf4j
@Component
public class MkHttpUtils {

    private Map<String, LogApiType> typeMap;

    private final LogApiMapper logApiMapper;


    @Value("${project.feign.qms-old-url}")
    private String qmsOldUrl;

    @Value("${project.feign.qms-url}")
    private String qmsUrl;

    @Value("${project.feign.ltk-url}")
    private String ltkUrl;

    @Value("${project.feign.ltk-pre-url}")
    private String ltkPreUrl;

    @Value("${project.feign.aps-url}")
    private String apsUrl;

    @PostConstruct
    public void init(){
        List<LogApiType> types = new ArrayList<>();

        // QMS 质量系统
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_BOM_ADD, qmsOldUrl + "/MasterBOM/BatchAddMasterBOM"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_BOM_UPDATE, qmsOldUrl + "/MasterBOM/BatchUpdateBOM"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_PHASE_ADD, qmsOldUrl + "/MasterProcessChain/BatchAddProcessChain"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_PHASE_UPDATE, qmsOldUrl + "/MasterProcessChain/BatchUpdateProcessChain"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_PART_START, qmsOldUrl + "/TaskInfo/AddTaskByPart"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_PART_END, qmsOldUrl + "/TaskInfo/EndTaskByPart"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_PLATE_START, qmsOldUrl + "/TaskInfo/AddTaskByPlate"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_PLATE_END, qmsOldUrl + "/TaskInfo/EndTaskByPlate"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_ASSEMBLY_START, qmsOldUrl + "/TaskInfo/AddTaskByModule"));
        types.add(new LogApiType(LogApiConstant.QMS, LogApiConstant.QMS_ASSEMBLY_END, qmsOldUrl + "/TaskInfo/EndTaskByModule"));
        // QMS 2.0 质量系统
        types.add(new LogApiType(LogApiConstant.QMS_SY, LogApiConstant.QMS_SY_PLATE_START, qmsUrl + "/task/generatePlateProcessTask"));
        types.add(new LogApiType(LogApiConstant.QMS_SY, LogApiConstant.QMS_SY_PLATE_END, qmsUrl + "/tbQmsPlate/syncPlatePartData"));
        types.add(new LogApiType(LogApiConstant.QMS_SY, LogApiConstant.QMS_SY_SMALL_PART_START, qmsUrl + "/task/generatePartTask"));
        types.add(new LogApiType(LogApiConstant.QMS_SY, LogApiConstant.QMS_SY_BIG_PART_START, qmsUrl + "/task/generateAssemblyTask"));
        // 兰特克套料接口
            // 兰特克正式套料
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_PUSH_DRAWING, ltkUrl + "/api/0114/BasePart/RegisterOrUpdate", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_PUSH_PLAN, ltkUrl + "/api/0114/ManufacturingOrder/Creates", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
            // 兰特克预套料
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_PRE_PUSH_DRAWING, ltkPreUrl + "/api/0114/BasePart/RegisterOrUpdate", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_PRE_PUSH_PLAN, ltkPreUrl + "/api/0114/ManufacturingOrder/Creates", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
            // 兰特克其余接口
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_RECEIVE_NEST, apsUrl + "/sinoCam/receiveNest"));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_DELETE_PLAN, ltkUrl + "/api/0114/ManufacturingOrder/Delete", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_DELETE_DRAWING, ltkUrl + "/api/0114/BasePart/Delete", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_UPDATE_PLAN, ltkUrl + "/api/0114/ManufacturingOrder/Updates", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_REPLACE_PLAN, ltkUrl + "/api/0114/ManufacturingOrder/HighQualityReplacingLowQuality", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_WITHDRAW_NEST, ltkUrl + "/api/0114/ManufacturingOrder/ProgramWithdrawal", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_CREATE_PLATE, ltkUrl + "/api/0114/SteelPlate/SaveSteelPlate", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));
            // 兰特克预套料删除接口
        types.add(new LogApiType(LogApiConstant.LTK, LogApiConstant.LTK_DELETE_PREORDER, ltkPreUrl + "/api/0114/ManufacturingOrder/Delete", "$$HEAD$$Authorization", LtkPushTokenDto.TOKEN));

        typeMap = types.stream().collect(Collectors.toMap(e -> String.join("_", e.getType(), e.getCode()), Function.identity()));
    }


    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public ApiResponse postForm(String type, String name, String id, Map<String, Object> params, BiConsumer<LogApi, String> consumer){
        ApiResponse apiResponse = new ApiResponse();

        LogApiType logApiType = typeMap.get(String.join("_", type, name));
        LogApi logApi = initLog(id, params, type, name, logApiType);
        apiResponse.setLogApi(logApi);

        try {
            String resJsonStr = HttpUtil.post(logApi.getUrl(), params);
            apiResponse.setBody(resJsonStr);

            FileUtil.writeString(resJsonStr, logApi.getResponsePath(), StandardCharsets.UTF_8);
            if(consumer == null){
                logApi.setSuccess(true);
                logApi.setErrorMsg(null);
                return apiResponse;
            }
            consumer.accept(logApi, resJsonStr);
            return apiResponse;
        } catch (Exception e){
            logApi.setSuccess(false);
            logApi.setErrorMsg(e.getMessage());
            return apiResponse;
        } finally {
            logApi.setWorkTime(System.currentTimeMillis() - logApi.getWorkTime());
            logApiMapper.insert(logApi);
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public ApiResponse postJson(String type, String name, String id, Object params, BiConsumer<LogApi, String> consumer){

        ApiResponse apiResponse = new ApiResponse();
        LogApiType logApiType = typeMap.get(String.join("_", type, name));
        LogApi logApi = initLog(id, params, type, name, logApiType);
        apiResponse.setLogApi(logApi);

        try {
            HttpRequest httpRequest = HttpRequest.post(logApi.getUrl());

            if (logApiType.getAttr() != null) {
                List<String> headers = logApiType.getAttr().keySet().stream().filter(e -> e.startsWith("$$HEAD$$")).collect(Collectors.toList());
                for (String header : headers) {
                    httpRequest.header(header.substring(8), logApiType.getAttr().get(header));
                }

            }

            String resJsonStr = httpRequest
                    .body(JsonUtils.toJsonString(params))//表单内容
                    .execute().body();
            apiResponse.setBody(resJsonStr);
            FileUtil.writeString(resJsonStr, logApi.getResponsePath(), StandardCharsets.UTF_8);
            if(consumer == null){
                logApi.setSuccess(true);
                logApi.setErrorMsg(null);
//                return resJsonStr;
                return apiResponse;
            }
            consumer.accept(logApi, resJsonStr);
//            return resJsonStr;
            return apiResponse;
        } catch (Exception e){
            logApi.setSuccess(false);
            if(e.getMessage()!=null&&e.getMessage().length()>200){
                logApi.setErrorMsg(e.getMessage().substring(0,200));
            }else{
                logApi.setErrorMsg(e.getMessage());
            }

            return apiResponse;
        } finally {
            logApi.setWorkTime(System.currentTimeMillis() - logApi.getWorkTime());
            logApiMapper.insert(logApi);
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public ApiResponse deleteJson(String type, String name, String id, Object params, BiConsumer<LogApi, String> consumer){

        ApiResponse apiResponse = new ApiResponse();
        LogApiType logApiType = typeMap.get(String.join("_", type, name));
        LogApi logApi = initLog(id, params, type, name, logApiType);
        apiResponse.setLogApi(logApi);

        try {
            HttpRequest httpRequest = HttpRequest.delete(logApi.getUrl());

            if (logApiType.getAttr() != null) {
                List<String> headers = logApiType.getAttr().keySet().stream().filter(e -> e.startsWith("$$HEAD$$")).collect(Collectors.toList());
                for (String header : headers) {
                    httpRequest.header(header.substring(8), logApiType.getAttr().get(header));
                }

            }

            String resJsonStr = httpRequest
                    .body(JsonUtils.toJsonString(params))//表单内容
                    .execute().body();
            apiResponse.setBody(resJsonStr);
            FileUtil.writeString(resJsonStr, logApi.getResponsePath(), StandardCharsets.UTF_8);
            if(consumer == null){
                logApi.setSuccess(true);
                logApi.setErrorMsg(null);
//                return resJsonStr;
                return apiResponse;
            }
            consumer.accept(logApi, resJsonStr);
//            return resJsonStr;
            return apiResponse;
        } catch (Exception e){
            logApi.setSuccess(false);
            if(e.getMessage()!=null&&e.getMessage().length()>200){
                logApi.setErrorMsg(e.getMessage().substring(0,200));
            }else{
                logApi.setErrorMsg(e.getMessage());
            }

            return apiResponse;
        } finally {
            logApi.setWorkTime(System.currentTimeMillis() - logApi.getWorkTime());
            logApiMapper.insert(logApi);
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public ApiResponse putJson(String type, String name, String id, Object params, BiConsumer<LogApi, String> consumer){

        ApiResponse apiResponse = new ApiResponse();
        LogApiType logApiType = typeMap.get(String.join("_", type, name));
        LogApi logApi = initLog(id, params, type, name, logApiType);
        apiResponse.setLogApi(logApi);

        try {
            HttpRequest httpRequest = HttpRequest.put(logApi.getUrl());

            if (logApiType.getAttr() != null) {
                List<String> headers = logApiType.getAttr().keySet().stream().filter(e -> e.startsWith("$$HEAD$$")).collect(Collectors.toList());
                for (String header : headers) {
                    httpRequest.header(header.substring(8), logApiType.getAttr().get(header));
                }

            }

            String resJsonStr = httpRequest
                    .body(JsonUtils.toJsonString(params))//表单内容
                    .execute().body();
            apiResponse.setBody(resJsonStr);
            FileUtil.writeString(resJsonStr, logApi.getResponsePath(), StandardCharsets.UTF_8);
            if(consumer == null){
                logApi.setSuccess(true);
                logApi.setErrorMsg(null);
//                return resJsonStr;
                return apiResponse;
            }
            consumer.accept(logApi, resJsonStr);
//            return resJsonStr;
            return apiResponse;
        } catch (Exception e){
            logApi.setSuccess(false);
            if(e.getMessage()!=null&&e.getMessage().length()>200){
                logApi.setErrorMsg(e.getMessage().substring(0,200));
            }else{
                logApi.setErrorMsg(e.getMessage());
            }

            return apiResponse;
        } finally {
            logApi.setWorkTime(System.currentTimeMillis() - logApi.getWorkTime());
            logApiMapper.insert(logApi);
        }
    }

    private LogApi initLog(String id, Object params, String type, String name, LogApiType logApiType) {
        LogApi logApi = new LogApi();
        logApi.setAppId(LogApiUtils.SERVER_NAME);
        logApi.setDir(1);
        logApi.setSender(LogApiUtils.SERVER_NAME);
        logApi.setReceiver(logApiType.getType());
        logApi.setApiName(logApiType.getCode());
        logApi.setSuccess(false);
        logApi.setCallDateTime(LocalDateTime.now());
        logApi.setUrl(logApiType.getUrl());
        logApi.setWorkTime(System.currentTimeMillis());
        logApi.setRequestPath(JsonUtils.toJsonString(params));
        logApi.setRemark(id);
        String reqJson = JsonUtils.toJsonString(params);
        String reqPath = FileStorageUtils.getFilePath(FileStorageUtils.LOG_API_TYPE);
        String resPath = FileStorageUtils.getFilePath(FileStorageUtils.LOG_API_TYPE);
        logApi.setRequestPath(reqPath);
        logApi.setResponsePath(resPath);
        FileUtil.writeString(reqJson, new File(reqPath), "UTF-8");
        return logApi;
    }
}
